#!/usr/bin/env python
#samsterlicious when cut across the neck a sound like wailing winds is heard
'''
file transfer and recieve classes
these are called by ui's
'''
import socket, os, sys, threading, tempfile, re, time, math, random, string

buf = 10000

class recieve_thread(threading.Thread):
  # socket file sema
  def __init__(self,sockeet,file_p,semaz):
    threading.Thread.__init__(self)
    self.sema = semaz
    self.sock = sockeet
    self.file = file_p
  def run(self):
    csock, addr = self.sock.accept()
    msg = csock.recv(buf)
    #message = "filename size"
    reg_msg = msg.split("::")
    filename = reg_msg[0] 
    size = reg_msg[1]
    final_size = int(math.ceil((float(size)/buf)))
    self.sema.acquire()
    if(progress == {}):
        i = 0
        while i < final_size:
          progress[i] = 0
          i = i + 1
    self.sema.release()
    finished = False
    while finished == False:
        self.sema.acquire()
        if len(progress) == 0:
          finished = True
	  self.sema.release()
          self.sock.close()
          sys.exit(1)
        else:
          has_kizey = False
          while has_kizey == False:
            starting_key = 0
            while(not(progress.has_key(starting_key))):
                starting_key = starting_key + 1
            temp = 0
            for key in progress:
                temp = key
            i = random.randint(starting_key,temp)
            has_kizey = progress.has_key(i)
	print len(progress)
        self.sema.release()
        msg = str(i)
        csock.send(msg)
        file_part = csock.recv(buf+10)
        fp = int(file_part[0:10])
        self.sema.acquire()
        progress[fp] = 1
        index = fp * buf
        self.file.seek(index)
        self.file.write(file_part[10:len(file_part)])
        if(not progress.has_key(i)):
          finished = True
	  self.sema.release()
          self.sock.close()
          sys.exit(1)
        del progress[i]
        self.sema.release()
        

class send_thread(threading.Thread):
  def __init__(self,socketz,addr):
    threading.Thread.__init__(self)
    self.sock = socketz
    self.add = addr
  def run(self):
    #send 'filename size'
    #recieving msg requesting sam.txt port 5001
    a = self.sock.recv(buf)
    splitter = a.split('::')
    filez = open(splitter[0],'rb')
    size = os.path.getsize(splitter[0])
    msg = splitter[0] + '::' + str(size)
    total_parts = math.ceil(float(size)/float(buf))
    port_num = splitter[1]
    sockz = socket.socket()
    sockz.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    i = 0
    sockz.connect((self.add[0],int(port_num)))
    sockz.send(msg)
    while i < total_parts:
        a = sockz.recv(buf)
        if(a == ''): break
        index = float(a) * float(buf)
        index = math.floor(index)
        index = int(index)
        filez.seek(index)
        file_part = filez.read(buf)
        msg = a
        while len(msg) < 10:
          msg = msg + ' '
        sockz.send(msg+file_part)

#dict is the dictionary passed by the UI  name:filename and addr:[(ip,port)]
class file_recieve_request(threading.Thread):
  threadList = []

  def __init__(self,list_of_tuplez):
    threading.Thread.__init__(self)
    #you're getting passed a tuple
    global progress
    global finished
    progress = {}
    finished = False
    '''
    self.full_file_name = dict['name']
    splitter = dict['name'].split('/')
    self.file_name = splitter[len(splitter)-1]
    print self.file_name
    self.new_file = open(self.file_name,'wb')
    self.ip_list = dict['ip']
    '''

    windows_check = re.search('[\\\]',list_of_tuplez[0][2])
    linux_check = re.search('/',list_of_tuplez[0][2])
    if windows_check != None :
	temp = string.split(list_of_tuplez[0][2],'\\')
 	self.file_name = temp[len(temp)-1]
    elif linux_check != None :
	temp = string.split(list_of_tuplez[0][2],'/')
	self.file_name = temp[len(temp)-1]
    else:
	self.file_name = list_of_tuplez[0][2]
    self.new_file = open(self.file_name,'wb')
    self.list_of_tuples = list_of_tuplez
  def run(self):
  #send request for a file to each ip in the dictionary
    x = 5000
    count = 0
    sema = threading.Semaphore(1)
    while count < len(self.list_of_tuples):
        temp_sock = socket.socket()
        temp_sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        fail = True
        localhost = socket.gethostbyname(socket.gethostname())
	if(localhost == '127.0.0.1'):
	  try:
	    import commands
	    localhost = commands.getoutput("ifconfig").split("\n")[1].split()[1][5:]
	  except(Exception):
	     a = raw_input("you're using localhost type in your ip manually\n")
	     localhost = a
        while(fail == True):
          try:
            temp_sock.bind((localhost,x))
            fail = False
          except(Exception):
            x = x + 1
        temp_sock.listen(5)
        temp_thread = recieve_thread(temp_sock,self.new_file,sema)
        temp_thread.start()
        self.threadList.append(temp_thread)
        count = count + 1
    starting_port = x-len(self.list_of_tuples)+1
    try:
        for tupel in self.list_of_tuples:
          ip = str(tupel[0])
          port = int(tupel[1])
	  file_path = tupel[2]
          c_sock = socket.socket()
          c_sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
          c_sock.connect((ip,port))
          send_msg = file_path + "::" + str(starting_port)
          starting_port = starting_port+1
          c_sock.send(send_msg)
    except(KeyboardInterrupt, SystemExit):
        c_sock.close()
        exit(0)
        raise
    for i in self.threadList:
       i.join()
    print "Finished downloading "+self.file_name
